/**
*****************************************************************************
 * @file system.c
 * @brief SYS驱动
 * @author luffy
 * @version V1.0.0
 * @date 2022/12/13
****************************************************************************
 */
#include "system.h"
#include <stdbool.h>
#include "device_table.h"

#include "drv_f4_gpio.h"
#include "drv_f4_usart.h"
#include "drv_f4_delay_168MHz.h"

//#include "A_log.h"
//#include "A_para.h"
#include "A_shell.h"
#include "A_memory.h"
#include "A_aclass_protocol.h"
#include "A_backtrace.h"
#include "ParmManage.h"
#include "version.h"
#include "expand_io.h"
#include "SC16IS752.h"
#include "dev_rbm350.h"
#include "dev_ad7193_temp.h"
#include "dev_ad7193_press.h"
#include "step_motor.h"
#include "dev_time.h"
#include "led_task.h"

/* Private Struct ---------------------------------------------------------------*/

/* Private defines ---------------------------------------------------------------*/

/* Private enum ---------------------------------------------------------------*/
/* Private Variable ---------------------------------------------------------------*/

static uint8_t g_wokemode = SYS_MODE_WORK;      //工作模式

/* Private function prototypes -----------------------------------------------*/
static void shell_Idle_CallBack( uint8_t *data, uint32_t len);
static void Device_INFO_Init(void);

void sc16is752_a_Int_Callback(void);

int SpiFlashWrite(uint32_t addr, uint8_t *data,  size_t len);
int SpiFlashRead(uint32_t addr, uint8_t *data,  size_t len);
int SpiFlashErase(uint32_t addr, size_t len);
int FramFlashWrite(uint16_t addr, uint8_t *data,  uint16_t len);
int FramFlashRead(uint16_t addr, uint8_t *data,  uint16_t len);
int McuFlashWrite(uint32_t addr, uint8_t *data,  size_t len);
int McuFlashRead(uint32_t addr, uint8_t *data,  size_t len);
int McuFlashErase(uint32_t addr,  size_t len);

//Pointer
char device_info_msg[64];
char device_code[10];            //设备编码ID
//Array
static drv_flash_t m_flash; //内部flash
static dev_fm24_t m_fram =  //铁电
{
    .PIN_SCL = "A8",
    .PIN_SDA = "C9",
    .PIN_WP =  NULL,
    .chip_size = 8192,  //FM24CL64 内存大小：8192
};

drv_usart_t shell_usart = //调试串口
{
    .Drv_Num = "USART2",//"UART4",
    .Tx_Pin = "A2",
    .Rx_Pin = "A3",
    .BaudRate = 115200,
    .WordLength = USART_WORDLENGTH_8BIT,
    .StopBits = USART_STOPBITS_1BIT,
    .Parity = USART_PARITY_NO,
    .Idle_CallBack = shell_Idle_CallBack,
    .Rx_Priority = 5,
};

dev_dac8830_t dac8830 = //DAC8830
{
	.DRV = "SOFTSPI",   //由于8830可使用的SPI模式与其他SPI1不同，使用不能使用硬件SPI1，改用软件SPI
    .PIN_CS = "D13",
    .PIN_MOSI = "D12",
    .PIN_SCK = "D11",
	.PIN_CH = "D10",
	.REF_V = 2.5,
};

dev_adc7193_t adc7193_temp = //ADC7193
//dev_adc7193_t adc7193_press = //ADC7193
{
    .DRV = "SPI2",
    .PIN_CS = "B9",
    .PIN_MOSI = "B15",
    .PIN_MISO = "B14",
    .PIN_SCK = "B13",
	.PIN_A0 = "NULL",
	.PIN_A1 = "NULL",
    .SPI_SPEED = SPI_SPEED_MEDIUM, 
    .SPI_CS_MODE = SPI_CS_NULL, 
};

dev_adc7193_t adc7193_press = //ADC7193
//dev_adc7193_t adc7193_temp = //ADC7193
{
    .DRV = "SPI3", // 与w5500冲突
    .PIN_CS = "D2", 
    .PIN_MOSI = "C12",
    .PIN_MISO = "C11",
    .PIN_SCK = "C10",
	.PIN_A0 = NULL,
	.PIN_A1 = NULL,
    .SPI_SPEED = SPI_SPEED_SLOW, //SPI_SPEED_SLOW, //SPI_SPEED_MEDIUM,
    .SPI_CS_MODE = SPI_CS_NULL, 
};

dev_w25qxx_t m_w25q64 = //SPI flash
{
    .DEV = "M_SOFT_SPIFLASH",
    .DRV = "SOFTSPI",
    .PIN_CS = "A4",
    .PIN_MOSI = "A7",
    .PIN_MISO = "A6",
    .PIN_SCK = "A5",
    .PIN_WP = NULL,
    .PIN_RESET = NULL,
    .SPI_SPEED = SPI_SPEED_HIGH,
    .SPI_CS_MODE = SPI_CS_NULL,
    .Delay_ms = SoftDelayMs,
	.mem_type = W25Q64,
};

dev_tca6416_t tca6416 = //TCA6416(IO口扩展)
{
    .PIN_SDA = "A8",
    .PIN_SCL = "C9",
    .SLAVE_ADDR = 0x40,
	.Int_Callback = NULL,
};

//Const

/*****************************************************************************
* @brief shell写接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
static signed short SysShellWrite(char *data, unsigned short len)
{
    shell_usart.Write(&shell_usart, (uint8_t *)data, (uint32_t)len);
    return len;
}

/*****************************************************************************
* @brief SPI flash写接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int SpiFlashWrite(uint32_t addr, uint8_t *data,  size_t len)
{
    m_w25q64.Write(&m_w25q64, data, addr, len);
    return len;
}

/*****************************************************************************
* @brief SPI flash读接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int SpiFlashRead(uint32_t addr, uint8_t *data,  size_t len)
{
    m_w25q64.Read(&m_w25q64, data, addr, len);
    return len;
}

/*****************************************************************************
* @brief SPI flash擦接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int SpiFlashErase(uint32_t addr, size_t len)
{
    m_w25q64.EraseSector(&m_w25q64, addr, len);
    return len;
}

/*****************************************************************************
* @brief Fram flash写接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int FramFlashWrite(uint16_t addr, uint8_t *data,  uint16_t len)
{
    m_fram.Write(&m_fram, addr, data, len);
    return len;
}

/*****************************************************************************
* @brief Fram flash读接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int FramFlashRead(uint16_t addr, uint8_t *data,  uint16_t len)
{
    m_fram.Read(&m_fram, addr, data, len);
    return len;
}

/*****************************************************************************
* @brief 获取当前工作模式
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
uint8_t get_sys_wokemode(void)
{
    return g_wokemode;
}

/*****************************************************************************
* @brief 设置当前工作模式
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
void set_sys_wokemode(uint8_t mode)
{
    g_wokemode = mode;
}

/*
功能：掉电检测，存储测试过程的参数
参数：无
返回值：无
*/
void PVD_Init(void)
{
   EXTI_InitTypeDef EXTI_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;

   NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn;    
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

   PWR_PVDLevelConfig(PWR_PVDLevel_7);	//可设置范围0~7
   PWR_PVDCmd(ENABLE);

   EXTI_DeInit();
   EXTI_StructInit(&EXTI_InitStructure);
   EXTI_InitStructure.EXTI_Line = EXTI_Line16;	//PVD连接到外部中断16
   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;   //高电压下降到设定值时，产生中断
   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
   EXTI_Init(&EXTI_InitStructure);
}

//掉电中断处理函数
void  PVD_IRQHandler(void)
{
    uint8_t posindex = 0;

    Ashell_print("enetr POWER OFF\r\n");
   if(PWR_GetFlagStatus(PWR_FLAG_PVDO))
   {
		memcpy(&(data_server.press_par.record_pos), &posindex, sizeof(float));
		PPItemIWrite(PP_VALVE_POSINDEX, &posindex, 1);  
        if(RUNING == test_state)
        {
            poweroff_state = POWER_OFF_ON_RUNING;
            PPItemIWrite(PP_POWER_OFF_FLAG, &poweroff_state, 1);  
        } 
        else
        {
            poweroff_state = POWER_OFF_ON_FINISHED;
            PPItemIWrite(PP_POWER_OFF_FLAG, &poweroff_state, 1);
        }
        
   }
   EXTI_ClearITPendingBit(EXTI_Line16);
}

/*****************************************************************************
* @brief 系统设备初始化
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
void system_init(void)
{
    uint16_t self_check = 0;

    /* shell调试串口初始化*/
    if (Drv_Usart_Init(&shell_usart) < 0)
    {
        while (1);
    }
    AShellInit(SysShellWrite, NULL);

    /* IAP Flash存储管理初始化*/
    if (Dev_W25qxxInit(&m_w25q64) < 0)
    {
        self_check |= SPI_FLASH_ERROR;
    }
    
	/*FRAM 端口和读写控制初始化*/
    if (Dev_Fm24_Init(&m_fram) != 0)
    {
        self_check |= FRAM_ERROR;
    }
	
	/* 内部 flash 初始化 */
	Drv_Flash_Init(&m_flash);
	
	//注册MCU Flash分区基地址、大小、地址对齐、读写擦除控制函数
    Amem_Hardware_Register(M_CPU_FLASH, 0,STORAGE_APPLICATION_SIZE, 4,
                           McuFlashWrite,
                           McuFlashRead,
                           McuFlashErase);//mcu内部flash注册（stm32f407vgt6 1MB内存）
	//注册IAP Flash分区基地址、大小、地址对齐、读写擦除控制函数
    Amem_Hardware_Register(M_SOFT_SPIFLASH, 0, 0x1000000, 1,
                           SpiFlashWrite,
                           SpiFlashRead,
                           SpiFlashErase);//IAP升级读写，w25q64注册
	
	//MCU Flash分区配置
	Amem_Area_Register(M_UPAPP_AERA, M_CPU_FLASH,
                        STORAGE_BOOTLOADER_BASE, STORAGE_BOOTLOADER_SIZE);//升级程序区配置
    
    Amem_Area_Register(M_UPPARA_AERA, M_CPU_FLASH,
                        STORAGE_PARM_UPATAE_BASE, STORAGE_PARM_UPATAE_SIZE);//升级参数区配置
    
    Amem_Area_Register(M_APP_AERA, M_CPU_FLASH,
                        STORAGE_APPLICATION_BASE, STORAGE_APPLICATION_SIZE);//应用程序区配置
    
	//IAP Flash分区配置
    Amem_Area_Register(M_DOWNLOAD_AREA, M_SOFT_SPIFLASH,
                        STORAGE_DOWNLOAD_BASE, STORAGE_DOWNLOAD_SIZE);  //下载区内存配置
        
    Amem_Area_Register(M_LOG_AREA, M_SOFT_SPIFLASH,
                        STORAGE_LOG_BASE, STORAGE_LOG_SIZE);  //LOG区配置
						
//    Amem_Area_Register(M_SYSPARM_AREA, M_SOFT_SPIFRAM,
//                       FRAM_SYSTEM_PARAM_BASE, FRAM_SYSTEM_PARAM_SIZE);

/* log管理初始化*/
//    AlogInit(SysShellWrite, NULL);
	
	/* LED、蜂鸣器、限位开关、加热包控制GPIO口外设初始化*/
	SWITCH_init();
	//Dev_Tca6416_Init(&tca6416);
	
	
	//扩展IO模块初始化
    #if defined SUPPORT_LED_EXPAND
    Expand_IO_Init();          //LED控制IO驱动端口、读写控制模块初始化
    Expand_IO_Mode_Init();     //LED控制IO驱动端口全部输出高电平
    ExpandLed_Init();          //LED初始化
	#endif
    
    // DAC 初始化
    if(Dev_dac8830_Init(&dac8830) < 0)
    {
        while(1);
    }
		
		//比例阀输出初始电压
		dac8830.Write(&dac8830,0,0);
	
	// 温度采集ADC 初始化
	if(Dev_Adc7193_Temp_Init(&adc7193_temp) < 0){
		while(1);
	}
	
	//S1-S3,P0,BASE压力采集ADC初始化
	if(Dev_Adc7193_Press_Init(&adc7193_press) < 0){
		while(1);
	}

	// stepMotor 初始化
	step_motor_init();
	
	/* 参数管理初始化*/
    if (REG_PPInit(&m_flash, &m_fram) != 0){
        while(1);
	}

	/* 设备信息初始化*/
    Device_INFO_Init();
}

/*****************************************************************************
* @brief 调试串口接收回调函数
* ex:
* @par 输入参数：uint8_t *data - 接收到数据地址
*                uint32_t len - 接收到的数据长度
*      输出参数：无：
* None
* @retval 返回值：无
*****************************************************************************/
static void shell_Idle_CallBack(uint8_t *data, uint32_t len)
{
    Ashell_rx_callback(data, (uint16_t)len); //中断调用需将shell改为异步模式
}

/***********************************************************************************
 * @brief 设备信息初始化
 * ex:
 * @par
 * None
 * @par Called functions:
 * None
 * @retval void None
 **********************************************************************************/
static void Device_INFO_Init(void)
{
	char info[] = DEVICE_INFO;
    memcpy(device_info_msg,info,sizeof(DEVICE_INFO));
    PPItemIWrite(PP_DEVICE_INFO, (uint8_t *)device_info_msg, sizeof(DEVICE_INFO));   

   
}

/***********************************************************************************
 * @brief
  * ex:
  * @par
  * None
  * @retval void None
  * None
  **********************************************************************************/
void SetDeviceInfo(char *data, uint8_t len)
{
	uint8_t count = 0;

	for (uint8_t i=0; i<len; i++) {
		if (data[i] == '-') {
			count++;
		}
	}

	if (count != 3 || len >= 32) {
		return;
	}

	memcpy(device_info_msg, data, len);
	memset(device_info_msg+len, 0, 32-len);

	PPItemIWrite(PP_DEVICE_INFO, (uint8_t*)device_info_msg, 32);
}

void GetDeviceCode(void)
{
    uint8_t i = 0;
    uint8_t j = 0;
    uint8_t count = 0;
    for(i = 0;i < 63;i++)
    {
        if(device_info_msg[i] == '-')
        {
            count ++;
        }
        
        if(count == 7)
        {
             device_info_msg[i+1] = device_code[j];
            j++;
            if(j == 10) break;
        }
        
    }
}

void SetDeviceCode(char *data)
{
    uint8_t i = 0;
    uint8_t j = 0;
    uint8_t count = 0;
    for(i = 0;i < 63;i++)
    {
        if(data[i] == '-')
        {
            count ++;
        }
        
        if(count == 7)
        {
            device_code[j] = data[i+1];
            j++;
            if(j == 10) break;
        }
        
    }
}
/***********************************************************************************
 * @brief
  * ex:
  * @par
  * None
  * @retval void None
  * None
  **********************************************************************************/
uint8_t GetDeviceInfo(void)
{
    uint8_t i = 0, j = 0,count = 0;
	char temp[64], deviceinfo[64];
	memset(temp, 0, 64);
    memset(deviceinfo, 0, 64);
    PPItemRead(PP_DEVICE_INFO, (uint8_t *)temp, 64);

    for(i = 0;i < 63;i++)
    {
        if(temp[i] == '-')
        {
            count ++;
        }
       
        if(count == 7)
        {
            j++;
            if(j == 11) break;
        }
        
    }
    
    memcpy(device_info_msg, temp, i+1);
    return i+1;
}

static int sys_info(uint8_t argc, char **argv)
{
    //char data[64];
    //uint16_t i = 0;

    GetDeviceInfo();
    //Ashell_print("System information: %s\r\n", data);
//    Ashell_print("Alog       version: %s\r\n", ALOG_VERSION);
    Ashell_print("Ashell     version: %s\r\n", ASHELL_VERSION);
//    Ashell_print("Abacktrace version: %s\r\n", ABACKTRACE_VERSION);
//    Ashell_print("Atransfer  version: %s\r\n", ATRANSFER_VERSION);

//    if (self_check != 0)
//    {
//        Ashell_print("Board self-test failed code = %hu:", self_check);
//        for(i = 0; i < DEVICE_TABLE_NUM; i++)
//        {
//            if (device_table[i].point & self_check)
//            {
//                Ashell_print(" %s", device_table[i].name);
//            }
//        }
//        Ashell_print("\r\n");
//    }
    return 1;
}

/*****************************************************************************
* @brief MCU flash写接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int McuFlashWrite(uint32_t addr, uint8_t *data,  size_t len)
{
    m_flash.Write(&m_flash, addr, data, len);
    return len;
}

/*****************************************************************************
* @brief MCU flash读接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int McuFlashRead(uint32_t addr, uint8_t *data,  size_t len)
{
    m_flash.Read(&m_flash, addr, data, len);
    return len;
}

/*****************************************************************************
* @brief MCU flash擦接口
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
int McuFlashErase(uint32_t addr, size_t len)
{
    m_flash.Erase(&m_flash, addr, len);
    return len;
}

/*****************************************************************************
* @brief 远程升级开始回调
* ex:
* @par
* None
* @retval 
*****************************************************************************/
void IAP_PreCallback(void)
{
    ;
}

/*****************************************************************************
* @brief 远程升级结束回调
* ex:
* @par
* None
* @retval 
*****************************************************************************/
void IAP_EndCallback(void)
{
    ;
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), system, sys_info, Querying System Information);

/******************* (C) COPYRIGHT 2022 CIQTEK luffy *****END OF FILE****/
